<template>
  <div class="map-container">
    <transition name="fade">
      <div class="toast" v-show="showToast">未查询到相关数据</div>
    </transition>
    <div :id="mapId" :style="{ height: height }"></div>
    <div class="map-search" v-if="!readOnly">
      <el-select
        v-model="keyword"
        filterable
        clearable
        remote
        placeholder="查询地点"
        :remote-method="querySearchAsync"
        @change="handleSelect"
        :loading="loading"
        :disabled="disabled"
      >
        <el-option
          v-for="item in addressList"
          :key="item.address"
          :label="item.address"
          :value="JSON.stringify(item)"
        >
        </el-option>
      </el-select>
      <el-icon class="icon" size="18px" color="#409EFF"><Search /></el-icon>
    </div>
    <div class="full-screen" @click="onFullScreen">
      <fullIcon class="full-screen-icon" title="全屏"></fullIcon>
      <!-- <img class="full-screen-icon" :src="fullScreen" @click="onFullScreen" /> -->
    </div>
    <template v-if="readOnly">
      <div class="form-view">
        <div class="form-view-item w-50">
          <div class="label">经度:</div>
          <div class="value">{{ formData.longitude }}</div>
        </div>
        <div class="form-view-item w-50">
          <div class="label">纬度:</div>
          <div class="value">{{ formData.latitude }}</div>
        </div>
        <div class="form-view-item">
          <div class="label">详细地址:</div>
          <div class="value">{{ formData.address }}</div>
        </div>
      </div>
    </template>
    <el-form ref="mapForm" :model="formData" :rules="rules" :label-width="labelWidth" v-else>
      <div class="nautica">
        <div class="nautica-item">
          <el-form-item label="经度：" prop="longitude">
            <el-input
              v-model="formData.longitude"
              :disabled="disabled"
              @change="changeLng"
            ></el-input>
          </el-form-item>
        </div>
        <div class="nautica-item">
          <el-form-item label="纬度：" label-width="80px" prop="latitude">
            <el-input
              v-model="formData.latitude"
              :disabled="disabled"
              @change="changeLat"
            ></el-input>
          </el-form-item>
        </div>
        <div class="nautica-action">
          <el-button @click="query" :disabled="disabled">查询</el-button>
        </div>
      </div>
      <el-form-item class="foot-shim" label="详细地址：" prop="address">
        <el-input v-model="formData.address" placeholder="请查询或选择地图地点" disabled></el-input>
      </el-form-item>
    </el-form>
  </div>
</template>
<script setup>
import { Search } from '@element-plus/icons-vue'
import RfGIS from 'rfgis-amap'
import icon from '../static/position.svg'
// import fullScreen from '../static/full-screen.png'
import fullIcon from './full.vue'
import { ref, watch, onMounted, defineExpose } from 'vue'
// 获取用户位置
// 接受参数
const props = defineProps({
  mapId: {
    //用于创建地图的domID 非必要可不传
    type: String,
    default: Math.random().toString(36).substring(2)
  },
  readOnly: {
    //设置地图只读
    type: Boolean,
    default: false
  },
  disabled: {
    // 禁用
    type: Boolean,
    default: false
  },
  height: {
    // 高度
    type: String,
    default: '200px'
  },
  zoom: {
    // 地图缩放级别
    type: Number,
    // org.zoom || 10
    default: () => {
      const org = JSON.parse(sessionStorage.getItem('dept')) || {}
      return org.zoom || 10
    }
  },
  center: {
    // 中心点
    type: Array,
    default: () => {
      const org = JSON.parse(sessionStorage.getItem('dept')) || {}
      return [org.longitude || 114.3, org.latitude || 30.6]
    }
  },
  longitude: {
    type: [Number, String],
    default: ''
  },
  latitude: {
    type: [Number, String],
    default: ''
  },
  address: {
    type: String,
    default: ''
  },
  labelWidth: {
    type: String,
    default: '100px'
  },
  required: {
    type: Boolean,
    default: true
  },
  lngRequired: {
    type: Boolean,
    default: false
  },
  latRequired: {
    type: Boolean,
    default: false
  },
  mapKey: {
    //高德地图key
    type: String,
    default: localStorage.getItem('MAP_KEY') || '50ce66407329d74f185f9d5db84138ce'
  },
  SecurityConfig: {
    // 高德地图安全密钥
    type: Object,
    default: () => {
      return localStorage.getItem('SECURITY_CONFIG')
        ? JSON.parse(localStorage.getItem('SECURITY_CONFIG'))
        : {
            securityJsCode: 'b770bd7bfd352f641450ad377bb1e434'
          }
    }
  }
})
// 发送事件
const emits = defineEmits([
  'anewValidate',
  'zoomHandler',
  'change',
  'update:longitude',
  'update:latitude',
  'update:address',
  'propsRfgis'
])
// 地图实例
const mapForm = ref(null)
let rfgis = null // 地图实例方法
let keyword = ref('')
const addressList = ref([])
const showToast = ref(false)
const loading = ref(false)
let formData = ref({
  longitude: '',
  latitude: '',
  address: ''
})
// 规则
const validateLng = (rule, value, callback) => {
  if (props.required) {
    // 空值
    if (value == '') {
      callback(new Error('请输入查询的经度(范围在-180 ~ 180)'))
    }
  }
  // 有值
  if (value >= -180 && value <= 180) {
    callback()
  } else {
    callback(new Error('请正确输入查询的经度(范围在-180 ~ 180)'))
  }
}
const validateLat = (rule, value, callback) => {
  if (props.required) {
    // 空值
    if (value == '') {
      callback(new Error('请输入查询的纬度(范围在-90 ~ 90)'))
    }
  }
  // 有值
  if (value >= -90 && value <= 90) {
    callback()
  } else {
    callback(new Error('请正确输入查询的纬度(范围在-90 ~ 90)'))
  }
}

const changeLng = (val) => {
  console.log(val, props.longitude)
  if (!val) {
    formData.value.longitude = props.longitude
  }
}
const changeLat = (val) => {
  if (!val) {
    formData.value.latitude = props.latitude
  }
}
const rules = {
  longitude: [
    {
      required: props.lngRequired,
      validator: validateLng
      // trigger: 'change'
    }
  ],
  latitude: [
    {
      required: props.latRequired,
      validator: validateLat
      // trigger: 'change'
    }
  ],
  address: [{ required: props.required, message: '地址不能为空' }]
}
watch(
  () => props.longitude,
  (val) => {
    console.log('地图，经纬度')
    formData.value.longitude = val
    setMapPosition()
  }
)
watch(
  () => props.latitude,
  (val) => {
    formData.value.latitude = val
    setMapPosition()
  }
)
watch(
  () => props.address,
  (val) => {
    formData.value.address = val
  }
)
watch(
  () => props.zoom,
  (val) => {
    setMapZoom(val)
  }
)
watch(
  () => formData,
  () => {
    emits('anewValidate')
  },
  {
    deep: true
  }
)
// 初始化地图
const instanceMap = () => {
  window._AMapSecurityConfig = props.SecurityConfig
  const mapInstance = new RfGIS({
    key: props.mapKey, // 申请好的Web端开发者Key
    version: '2.0', // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15 2.0
    plugins: ['AMap.MouseTool', 'Map3D', 'AMap.AutoComplete'], // 需要使用的的插件列表，如比例尺'AMap.Scale'等
    AMapUI: {
      // 是否加载 AMapUI，缺省不加载
      version: '1.1', // AMapUI 缺省 1.1
      plugins: ['overlay/SimpleMarker'] // 需要加载的 AMapUI ui插件
    },
    Loca: {
      //缺省不加载Loca
      version: '2.0' // Loca 版本，缺省 1.3.2 2.3.2
    }
  })
  createMap(mapInstance)
}
const createMap = (mapInstance) => {
  mapInstance
    .createMap({
      id: props.mapId, // 地图容器id
      type: '2D', // 地图类型 2d 3d 不区分大小写 [选填]
      center: props.center, // 地图中心点 默认为[114,30] [选填]
      zoom: props.zoom, // 缩放级别 [选填]
      basemap: 'vec' //vec 矢量底图 img 卫星地图  [选填]
    })
    .then((res) => {
      // 创建成功 返回状态字段及实例对象
      rfgis = res.data
      initMap()
    })
}
const toastShowTime = (time = 1000) => {
  showToast.value = true
  setTimeout(() => {
    showToast.value = false
  }, time)
}
const initMap = () => {
  formData.value.longitude = props.longitude
  formData.value.latitude = props.latitude
  formData.value.address = props.address
  setMapPosition()
  rfgis.map.on('click', (e) => {
    if (props.readOnly || props.disabled) return
    const mapPoint = [e.lnglat.lng, e.lnglat.lat]
    handlerPoint(mapPoint)
  })
  rfgis.map.on('zoomend', () => {
    const zoom = rfgis.map.getZoom()
    emits('zoomHandler', zoom)
  })
  emits('propsRfgis', rfgis)
  changeTheme()
  listenerTheme()
}
// 主题变化监听
let styleName = '' // 主题名称
const listenerTheme = () => {
  window.addEventListener('storage', function () {
    changeTheme()
  })
}
const changeTheme = () => {
  const theme = window.localStorage.getItem('map-theme-name')
  if (theme && styleName !== theme) {
    styleName = theme
    rfgis.map.setMapStyle('amap://styles/' + styleName)
  }
}
const setMapPosition = () => {
  if (props.longitude && props.latitude) {
    addMapPoint([props.longitude, props.latitude])
    moveMapCenterTo([props.longitude, props.latitude])
  } else {
    // this.setLocalCoords();
  }
}
const handlerPoint = ([longitude, latitude]) => {
  rfgis.removeAll()
  getAddressText([longitude, latitude]).then((res) => {
    if (res.regeocode?.formattedAddress) {
      addMapPoint([longitude, latitude])
      moveMapCenterTo([longitude, latitude])
      formData.value.longitude = longitude
      formData.value.latitude = latitude
      formData.value.address = res.regeocode.formattedAddress
      emits('change', {
        longitude,
        latitude,
        address: formData.value.address
      })
      emits('update:longitude', longitude)
      emits('update:latitude', latitude)
      emits('update:address', formData.value.address)
    } else {
      toastShowTime(2000)
    }
  })
}
const addMapPoint = ([longitude, latitude]) => {
  if (!rfgis) return
  rfgis.removeAll()
  rfgis.addMarker({
    position: [longitude, latitude], //位置
    icon, //图标 SVG，gif,png 【不支持svg动画】
    width: '24px', // 图形大小
    height: '34px', // 图形大小
    offsetX: 0,
    offsetY: -25, // 偏移值
    attributes: {}
  })
}
const moveMapCenterTo = (center) => {
  if (!rfgis) return
  rfgis.viewGoTo({
    center,
    zoom: props.zoom
  })
}
const getAddressText = (location) => {
  return rfgis.locationToAddr({ location })
}
const query = () => {
  let flag = null
  mapForm.value.validateField(['longitude', 'latitude'], (valid) => {
    if (valid) {
      flag = valid
    }
  })
  if (!flag && formData.value.longitude && formData.value.latitude) {
    formData.value.address = ''
    emits('update:address', formData.value.address)
    handlerPoint([+formData.value.longitude, +formData.value.latitude])
  }
}

// 查询地址
const querySearchAsync = (queryString) => {
  const autoComplete = new rfgis.AMap.AutoComplete({ city: '全国' })
  // 根据关键字进行搜索
  if (queryString) {
    loading.value = true
    autoComplete.search(queryString, (status, result) => {
      let addrList = []
      if (result.tips && result.tips.length) {
        result.tips.forEach((v) => {
          addrList.push({
            address: v.name,
            district: v.district,
            longitude: v.location.lng,
            latitude: v.location.lat
          })
        })
      }
      addressList.value = addrList
      loading.value = false
    })
  } else {
    addressList.value = []
  }
}
// 选择
const handleSelect = (e) => {
  let val = {}
  try {
    val = JSON.parse(e)
  } catch {
    console.error('解析失败,请重新搜索')
  }
  if (val && val.longitude && val.latitude) {
    addressList.value = []
    handlerPoint([val.longitude, val.latitude])
  }
}
// 校验
const validate = (callback) => {
  mapForm.value.validate(callback)
}
// 全屏
const onFullScreen = () => {
  document.getElementById(props.mapId).requestFullscreen()
}
const setMapZoom = (val) => {
  rfgis?.map?.setZoom(val)
}

// 初始化
onMounted(() => {
  instanceMap()
})
defineExpose({
  validate
})
</script>

<style scoped lang="scss">
.full-screen {
  position: relative;
  color: var(--text-secondary);
  &::after {
    content: '';
    width: 30px;
    height: 30px;
    background: var(--map-tool-bg, #fff);
    display: block;
    position: absolute;
    top: -40px;
    right: 10px;
    z-index: 1;
    border-radius: 2px;
    overflow: hidden;
  }
  &:hover {
    opacity: 0.8;
  }
}
.full-screen-icon {
  position: absolute;
  top: -35px;
  right: 15px;
  cursor: pointer;
  z-index: 2;
  fill: var(--text-secondary, #999);
}
.map-container {
  position: relative;
  overflow: hidden;
  width: 100%;
  .toast {
    position: absolute;
    z-index: 9;
    color: #ff4d4f;
    background: #fff;
    box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.16);
    padding: 0px 8px;
    border-radius: 4px;
    right: 15px;
    top: 10px;
  }
  .map-search {
    z-index: 1;
    position: absolute;
    top: 20px;
    left: 20px;
    :deep(.el-input__wrapper) {
      width: 200px;
      padding-left: 40px;
      box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.16);
      font-size: 14px;
      height: 32px;
      line-height: 32px;
      background: transparent;
      &:after {
        content: '';
        position: absolute;
        width: calc(100% - 2px);
        height: calc(100% - 2px);
        background-color: var(--map-tool-bg);
        opacity: 0.8;
        left: 1px;
        top: 1px;
        z-index: -1;
        border-radius: 4px;
      }
    }
    :deep(.el-select__input) {
      padding-left: 28px;
      width: 100% !important;
    }
    :deep(.el-select__placeholder) {
      padding-left: 28px;
    }
    :deep(.el-input__inner) {
      line-height: 32px;
    }
    .icon {
      position: absolute;
      left: 10px;
      top: 8px;
    }
  }
}
.foot-shim {
  // padding-bottom:18px !important;
}
.nautica {
  margin-top: 10px;
  display: flex;
  justify-content: space-between;
  &-item {
    display: flex;
    align-items: center;
    flex-grow: 1;
    &-label {
      flex-shrink: 0;
    }
    :deep(.el-form-item) {
      width: 100%;
      margin-bottom: 18px;
    }
  }
  &-action {
    margin-left: 20px;
  }
}
.form-view {
  display: flex;
  flex-wrap: wrap;
  &-item {
    width: 100%;
    line-height: 24px;
    padding: 2px 0;
    display: flex;
    align-items: baseline;
    justify-content: flex-start;
  }
  .label {
    padding-right: 12px;
    display: inline-block;
    word-break: keep-all;
  }
  .value {
    line-height: 24px;
  }
  .w-50 {
    width: 50%;
  }
}
</style>
